﻿using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using VXCompany.SilverlightLogging.ServiceProxy;

namespace VXCompany.SilverlightLogging.MVVM.Models.Stores
{
	/// <summary>
	/// Base class for Store types.
	/// </summary>
	public abstract class Store : NotifyingBase, IStore
	{
		/// <summary>
		/// Gets the innerlist.
		/// </summary>
		protected ObservableCollection<ExceptionMessage> InnerList { get; set; }
		private bool isInit = false;
		#region IStore Members

		private bool _IsStorageAvailable;

		/// <summary>
		/// Gets a value indicating whether the store is available.
		/// </summary>
		public bool IsStorageAvailable
		{
			get { return _IsStorageAvailable; }
			protected set
			{
				_IsStorageAvailable = value;
				base.RaisePropertyChanged("IsStorageAvailable");
			}
		}

		/// <summary>
		/// Gets behavior name.
		/// </summary>
		public virtual string Name
		{
			get { return this.GetType().Name; }
		}

		/// <summary>
		/// Gets ExceptionMessage items by minlevel.
		/// </summary>
		/// <param name="minLevel"></param>
		/// <returns></returns>
		public virtual IEnumerable<ExceptionMessage> GetByMinLevel(ServiceProxy.ErrorLevel minLevel)
		{
			if (IsStorageAvailable)
			return
				from item in this
				where item.Level >= minLevel
				select item;

			return null;
		}

		/// <summary>
		/// Prepares store for use.
		/// </summary>
		protected void Initialize()
		{
			if (!isInit)
			{
				this.IsStorageAvailable = true;
				InnerList = new ObservableCollection<ExceptionMessage>();
				InitializeImpl();
				if (this.IsStorageAvailable)
				{
					GetItemsFromStore().ForEach(item => InnerList.Add(item));
					InnerList.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(_innerList_CollectionChanged);
				}
				isInit = true;
			}
		}

		/// <summary>
		/// Removes range of ExceptionMessage entries.
		/// </summary>
		/// <param name="messages"></param>
		public virtual void RemoveRange(IEnumerable<ExceptionMessage> messages)
		{
			if (IsStorageAvailable)
			{				
				messages.ForEach(item => 
					{
						var found = (from i in this
									 where i.ExceptionMessageID == item.ExceptionMessageID
									 select i).First();
						this.Remove(found);
					});
			}
		}
				
		#endregion

		#region ICollection<ExceptionMessage> Members

		public void Add(ExceptionMessage item)
		{
			InnerList.Add(item);
		}

		public void Clear()
		{
			InnerList.Clear();
		}

		public bool Contains(ExceptionMessage item)
		{
			throw new System.NotImplementedException();
		}

		public void CopyTo(ExceptionMessage[] array, int arrayIndex)
		{
			throw new System.NotImplementedException();
		}

		public int Count
		{
			get { return InnerList.Count; }
		}

		public bool IsReadOnly
		{
			get { return false; }
		}

		public bool Remove(ExceptionMessage item)
		{
			return InnerList.Remove(item);
		}

		#endregion

		#region IEnumerable<ExceptionMessage> Members

		public IEnumerator<ExceptionMessage> GetEnumerator()
		{
			return InnerList.GetEnumerator();
		}

		#endregion

		#region IEnumerable Members

		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
		{
			return InnerList.GetEnumerator();
		}

		#endregion

		#region INotifyCollectionChanged Members

		public event System.Collections.Specialized.NotifyCollectionChangedEventHandler CollectionChanged;

		#endregion		

		/// <summary>
		/// Saves changes.
		/// </summary>
		protected void Save()
		{
			try
			{
				if (IsStorageAvailable)
					SaveImpl();
			}
			catch 
			{
				IsStorageAvailable = false;
			}
		}

		/// <summary>
		/// Saves changes.
		/// </summary>
		protected abstract void SaveImpl();

		/// <summary>
		/// Returns all ExceptionMessage items from the store.
		/// </summary>
		/// <returns></returns>
		protected abstract IEnumerable<ExceptionMessage> GetItemsFromStore();

		/// <summary>
		/// Prepares store for use.
		/// </summary>
		protected abstract void InitializeImpl();

		/// <summary>
		/// Eventhandler for the CollectionChanged event. Saves changes, relays event.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void _innerList_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
		{				
			if (this.CollectionChanged != null)
			{
				CollectionChanged(this, e);
			}
			Save();
		}
	}	
}
